/* fsm.c*/
#include "stdio.h"


typedef unsigned char   u8;     //  8 bits
typedef unsigned int    u16;    // 16 bits
typedef unsigned long   u32;    // 32 bits

typedef signed char     int8;   //  8 bits
typedef signed int      int16;  // 16 bits
typedef signed long     int32;  // 32 bits

typedef unsigned char   uint8;  //  8 bits
typedef unsigned int    uint16; // 16 bits
typedef unsigned long   uint32; // 32 bits

typedef unsigned char   uint8_t;  //  8 bits
typedef unsigned int    uint16_t; // 16 bits
typedef unsigned long   uint32_t; // 32 bits

 /*********** FSM-FUNPOINTER-CORE-START ***********/
typedef struct FsmTable_s
{
    uint8_t event;                /* 触发事件 */
    uint8_t CurState;             /* 当前状态 */
//    void (*eventActFun)(void *);  /* 动作函数 */
    void (*eventActFun)();  /* 动作函数 */
    void (*eventStateFun)();  /* 事件条件函数，状态函数，在没有进入其他状态维持的函数，为了模块化，所以单独拎出来 */
    uint8_t NextState;            /* 跳转状态 */
}FsmTable_T;

typedef struct FSM_s
{
    FsmTable_T *FsmTable;         /* 状态迁移表 */
    uint8_t curState;             /* 状态机当前状态 */
    uint8_t stuMaxNum;            /* 状态机状态迁移数量 */
}FSM_T;

/*==================================================================
* Function  : FSM_Init
* Description : 状态机初始化(注册和初始化,给它一个状态表)
* Input Para  : pFsm状态机对象，pTable状态迁移表，stuMaxNum迁移表数量
*               curState当前状态
* Output Para :
* Return Value:
==================================================================*/
void FSM_Init(FSM_T *pFsm, FsmTable_T *pTable, uint8_t stuMaxNum, uint8_t curState)
{
    pFsm->FsmTable = pTable;/*状态机注册,给它一个状态表*/
    pFsm->curState = curState;
    pFsm->stuMaxNum = stuMaxNum;
}

/*==================================================================
* Function  : FSM_EventHandle
* Description : 状态机处理函数
* Input Para  : pFsm状态机对象, event触发事件, parm动作执行参数
* Output Para :
* Return Value:
==================================================================*/
void (*eventStateFun)() = NULL;
//void FSM_EventHandle(FSM_T *pFsm, uint8_t event, void *parm)//如果执行的函数需要传参，可以添加void *parm 来传参
void FSM_EventHandle(FSM_T *pFsm, uint8_t event)
{
    FsmTable_T *pAcTable = pFsm->FsmTable;//定义一个状态迁移表指针
//    void (*eventActFun)(void *) = NULL;//定义一个动作的函数指针,函数指针初始化为空
    void (*eventActFun)() = NULL;//定义一个动作的函数指针,函数指针初始化为空

    uint8_t NextState;                 //定义下一个状态的变量
    uint8_t CurState = pFsm->curState;//定义当前状态的变量
    uint8_t flag = 0;                //匹配状态和事件的 标志

    for (uint8_t i = 0; i < pFsm->stuMaxNum; i++)// 遍历状态表
    {
        if (event == pAcTable[i].event && CurState == pAcTable[i].CurState) //当且仅当当前状态下来个指定的事件;注意CurState = pFsm->curState;
        {
            flag = 1;
            eventActFun = pAcTable[i].eventActFun;
            eventStateFun = pAcTable[i].eventStateFun;
            NextState = pAcTable[i].NextState;
            break;
        }
    }
    if (flag)
    {
        flag = 0;//only run once
        if (eventActFun != NULL)
        {
//            eventActFun(parm);  // 执行相应动作
            eventActFun();  // 执行相应动作,不需要传参时
        }
        pFsm->curState = NextState;		// 状态转换,这个是执行状态表首位，切上文中CurState取得就是此值
    }
    else
    {
//        printf("there is no match\n");

        if (eventStateFun != NULL)//每次进来指针都会初始化
        {
//            printf("eventStateFun runing\n");
            eventStateFun();  // 执行相应状态函数,不需要传参时
        }
    }

}
 /*********** FSM-FUNPOINTER-CORE-END ***********/

 /* 触发事件 */
typedef enum {
    EVENT1 = 1,
    EVENT2,
    EVENT3,
    EVENT4,
    EVENT5,
}event_code_t;//类型的别名

event_code_t event_code;

/* 状态对应的值 */
enum {
    STATE1 = 1,
    STATE2,
    STATE3,
    STATE4,
    STATE5,
}state_code;

/* cation fun */
void action_1(void)
{
  printf("action_1\n");
//  event_code = EVENT2;
}

void action_2(void)
{
  printf("action_2\n");
//  event_code = EVENT3;
}

void action_3(void)
{
  printf("action_3\n");
//  event_code = EVENT4;
}

void action_4(void)
{
  printf("action_4\n");
//  event_code = EVENT5;
}

void action_5(void)
{
  printf("action_5\n");
//  event_code = EVENT1;
//  event_code = EVENT0;//end loop keep in state1
}
//    {EVENT1,STATE1,action_2,state_2,STATE2},
//    {EVENT2,STATE2,action_3,state_3,STATE3},
//    {EVENT3,STATE3,action_4,state_4,STATE4},
//    {EVENT4,STATE4,action_5,state_5,STATE5},
//    {EVENT5,STATE5,action_1,state_1,STATE1},
void state_1(void)
{
  printf("state_1\n");
  event_code = EVENT1;
}

/* cation fun */
void state_2(void)
{
  printf("state_2\n");
  event_code = EVENT2;
}

void state_3(void)
{
  printf("state_3\n");
  event_code = EVENT3;
}

void state_4(void)
{
  printf("state_4\n");
  event_code = EVENT4;
}
int stop_flag = 0;
void state_5(void)
{
  static int i = 0;
  printf("state_5\n");
  if(++i>5)
  {
    event_code = EVENT5;//end loop keep in state1
    stop_flag = 1;
  }

}

FsmTable_T pFsmTable[] = {

//{到来的事件，当前的状态，将要要执行的函数，下一个状态}
//第一次进去FSM_EventHandle,pFsm->curState = NextState;状态机已经指向下一个State
    {EVENT1,STATE1,action_2,state_2,STATE2},
    {EVENT2,STATE2,action_3,state_3,STATE3},
    {EVENT3,STATE3,action_4,state_4,STATE4},
    {EVENT4,STATE4,action_5,state_5,STATE5},
    {EVENT5,STATE5,action_1,state_1,STATE1},

    //add your codes here

};

int main(void)
{

    FSM_T pFsm;
    FSM_Init(&pFsm,pFsmTable,sizeof(pFsmTable)/sizeof(FsmTable_T),STATE1);
    event_code = EVENT1;
    while(1)
    {
         FSM_EventHandle(&pFsm,event_code);
        if (stop_flag != 0)
            break;
    }
    return 0;
}
